package com.twoscreen;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

public class YouTubeInfoServlet extends HttpServlet {
	private static final Logger log = Logger.getLogger("com.twoscreen.YouTubeSendAuthServlet.java");
	private static final long serialVersionUID = 1L;
	private static final String clientID = "859612904977.apps.googleusercontent.com";
	private static final String callbackURI = "https://two-screen.appspot.com/oauth2callback";
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) {
		int code = 0;
		String viewerId = null;
		String ytc = null;
		TUser tuser = null;
		String token = null;
		String send = null;
		
		if (request.getParameter("code") != null) {
			code = Integer.parseInt(request.getParameter("code"));
			log.info("code received: " + code);
		}
		if (request.getParameter("ytc") != null) {
			ytc = request.getParameter("ytc");
			log.info("ytc received: " + ytc);
		}
		
		UserService userService = UserServiceFactory.getUserService();
		User user = null;
		try {
			user = userService.getCurrentUser();
			tuser = TUser.getTUser(user);
			viewerId = tuser.getViewerId();
		} catch (Exception e) {
			log.warning("Error getting the user: " + e);
		}
		
		//Ensure the user is valid before processing
		if (tuser != null) {
			switch (code) {
			
			case 0:
				//Start OAuth tokens retrieval - redirects to YouTubeAuthTokensServlet
				log.info("Initialising OAuth request");
				String authURL = "https://accounts.google.com/o/oauth2/auth?" +
					"client_id=" + clientID +
					"&redirect_uri=" + callbackURI +
					"&scope=https://gdata.youtube.com"+
					"&response_type=code"+
					"&access_type=offline" +
					"&state=" + viewerId;
				try {
					response.sendRedirect(authURL);
					log.info("Sent redirect");
				} catch (IOException e) {
					log.warning("Redirect failed " + e);
				}
				break;
				
			case 1:
				if (ytc != null) {
					//User's upload video wall request with passed YouTube code
					log.info("User's upload video wall requested with passed YouTube code");
					token = ytc;
				} else {
					//User's upload video wall with authorisation code requested
					log.info("User's upload video wall with authorisation code requested");
					token = tuser.getProducerAccessToken();
				}
				
				send = getVideoFeed(token);
				
				response.setContentType("application/json, charset=UTF-8");
				try {
					response.getWriter().println(send);
					log.info("User's videos sent");
				} catch (IOException e) {
					log.warning("User video wall response error: " + e.getMessage());
				}
				break;
				
			default:
				log.warning("Invalid request code received: " + code);
				break;
			
			}
		} else {
			log.warning("User not validated");
		}
		
	}
	
	private static String getVideoFeed(String token) {
		JSONObject rtnJSON = new JSONObject();
		Boolean connectionOK = false;
		int responseCode = 0;
		
		//Get the authorisation codes
		log.info("Getting videos from YouTube server");
		String requestURL = "https://gdata.youtube.com/feeds/api/users/default/uploads?alt=json&format=5";
		
		//Send get message
	    try {
	        URL url = new URL(requestURL);
	        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
	        connection.setDoOutput(true);
	        connection.setRequestMethod("GET");
	        connection.addRequestProperty("GData-Version", "2");
	        connection.addRequestProperty("X-GData-Key", "key=AI39si7jV6y8myoTri9Z2xsHhwDbX7vZEU3BWUG6Ymhshy63rv9nHUeVPsdb_LhzaivQbqplt8fZvEIYP3c5M0MMLyDwpqxUiQ");
	        connection.addRequestProperty("Authorization", "Bearer " + token);

	        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
	        	connectionOK = true;
	        	log.info("ok");
	        	rtnJSON.put("status", "ok");
	        	StringBuilder sb = new StringBuilder();
				BufferedReader reader = null;
			    try {
			        reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			        for (String line; (line = reader.readLine()) != null;) {
			            sb.append(line);
			            log.info("adding: " + line);
			        }
			    } finally {
			        if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
			    }
			    String youtubeJson = sb.toString();
			    log.info("Got the data from YouTube servers");
			    
			    try {
			    	JSONObject obj = new JSONObject(youtubeJson);
					log.info("JSON object is: " + obj);
					JSONObject feed = obj.getJSONObject("feed");
					log.info("JSON feed is: " + feed);
					JSONArray entry = feed.getJSONArray("entry");
					log.info("JSON entry is: " + entry);
					rtnJSON.put("entry", entry);
				} catch (Exception e) {}
	        } else {
	        	responseCode = connection.getResponseCode();
	        }
	        
	    } catch (MalformedURLException e) {
	    	log.warning("Malformed URL in Auth token request: " + e);
	    } catch (IOException e) {
	    	log.warning("IO exception in Auth token request: " + e);
	    } catch (JSONException e) {
	    	log.warning("JSON exception: " + e);
		}
	    
	    if (!connectionOK) {
	    	// Server returned HTTP error code - some codes are defined by the YouTube API
	    	try {
		    	if (responseCode != 0) {
		    		//YouTube feed returned error - return error message to browser
		    		log.severe("error" + responseCode);
		    		rtnJSON.put("status", "error");
		    		switch (responseCode) {
		    		case 401:
		    			rtnJSON.put("message", "YouTube account not linked");
		    			break;
		    			
		    		case 403:
		    			rtnJSON.put("message", "YouTube signup not completed");
		    			break;
		    			
	    			default:
	    				rtnJSON.put("message", responseCode);
	    				break;
		    		}
		    	} else {
		    		//HTTP connection error or a YouTube account error
		    		log.severe("error with YouTube video wall feed");
		    		rtnJSON.put("status", "error");
		    		rtnJSON.put("message", "connection or account");
		    	}
	    	} catch (Exception e) {
	    		log.warning("JSON exception: " + e);
	    	}
	    }
	    
		return rtnJSON.toString();
	}

}
